package com.jiyongjun.component.core.impl;

import com.jiyongjun.component.core.model.DubboLogContext;
import com.jiyongjun.component.core.model.LogContext;
import com.jiyongjun.component.enums.LogConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.rpc.Invocation;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

/**
 * <h2></h2>
 * <h3>描述：为了解决hsf调用超时问题，如果超时，客户端接收到响应结果的线程跟请求发起的线程不是同一个。</h3>
 *
 * @author yongjun.jyj
 * @since 2022/7/14 21:04
 */
@Slf4j
public class DubboClientTimeoutLogContextMap {
    private static final int TEN_MINUTES = 10 * 60 * 1000;
    private static final AtomicLong COUNTER = new AtomicLong(0);

    private static final Long SIZE_THRESHOLD = 50000L;

    private static final Map<Invocation, DubboLogContext> INVOCATION_LOG_CONTEXT_MAP = new ConcurrentHashMap<>();

    public static boolean put(Invocation invocation, DubboLogContext logContext) {
        if (INVOCATION_LOG_CONTEXT_MAP.size() > SIZE_THRESHOLD) {
            log.warn("{}|CLIENT请求日志过多|size={}", LogConstant.LOG_WARN_KEYWORD, INVOCATION_LOG_CONTEXT_MAP.size());
            return false;
        }

        COUNTER.incrementAndGet();
        INVOCATION_LOG_CONTEXT_MAP.put(invocation, logContext);

        return true;
    }

    public static DubboLogContext remove(Invocation invocation) {
        DubboLogContext logContext = INVOCATION_LOG_CONTEXT_MAP.remove(invocation);
        // todo
        // if (COUNTER.get() % 10000 == 0 && !INVOCATION_LOG_CONTEXT_MAP.isEmpty()) {
        //     long t1 = System.currentTimeMillis();
        //     log.info("{}|清理CLIENT过期日志|size={},start={}", LogConstant.LOG_INFO_KEYWORD, INVOCATION_LOG_CONTEXT_MAP.size(), t1);
        //     // 清理过期日志
        //     boolean remove = INVOCATION_LOG_CONTEXT_MAP.entrySet()
        //             .removeIf(entry -> t1 - entry.getKey().getStartTime() > TEN_MINUTES);
        //     if (remove) {
        //         log.error("{}|清理CLIENT过期日志|size={},elapsedTime={}", LogConstant.LOG_EXCEPTION_KEYWORD,
        //                 INVOCATION_LOG_CONTEXT_MAP.size(), System.currentTimeMillis() - t1);
        //     }
        // }
        return logContext;
    }

}
